package main

import (
	"encoding/json"
	"fmt"
	"github.com/robfig/config"
	"io/ioutil"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"time"
)

var (
	video_path       string
	video_after_path string
	logoPath         string
	videoSuffix      []string
	exec_thread      int
)

type StreamsInfo struct {
	Streams []StreamInfo `json:"streams"`
}
type StreamInfo struct {
	Width    int    `json:"width"`
	Height   int    `json:"height"`
	Bit_rate string `json:"bit_rate"`
}

func execCmdInfo(cmd *exec.Cmd) StreamsInfo {
	var modelInfo StreamsInfo
	for {
		stdout, err := cmd.StdoutPipe()
		if err != nil {
			fmt.Println("StdoutPipe: " + err.Error())
			break
		}

		stderr, err := cmd.StderrPipe()
		if err != nil {
			fmt.Println("StderrPipe: ", err.Error())
			break
		}

		if err := cmd.Start(); err != nil {
			fmt.Println("Start: ", err.Error())
			break
		}
		bytesErr, err := ioutil.ReadAll(stderr)
		if err != nil {
			fmt.Println("ReadAll stderr: ", err.Error())
			break
		}

		if len(bytesErr) != 0 {
			fmt.Printf("stderr: %s\n", bytesErr)
			break
		}

		bytes, err := ioutil.ReadAll(stdout)
		if err != nil {
			fmt.Println("ReadAll stdout: ", err.Error())
			break
		}

		if err := cmd.Wait(); err != nil {
			fmt.Println("Wait: ", err.Error())
			break
		}
		err = json.Unmarshal(bytes, &modelInfo)
		if err != nil {
			fmt.Println("Unmarshal fail:%v", err)
		} else {
			fmt.Println("modelInfo:", modelInfo)
		}
	}
	return modelInfo
}
func execCmd(cmd *exec.Cmd, outfile string, ch chan int) {
	for {
		stdout, err := cmd.StdoutPipe()
		if err != nil {
			fmt.Println("StdoutPipe: " + err.Error())
			break
		}

		stderr, err := cmd.StderrPipe()
		if err != nil {
			fmt.Println("StderrPipe: ", err.Error())
			break
		}

		if err := cmd.Start(); err != nil {
			fmt.Println("Start: ", err.Error())
			break
		}
		bytesErr, err := ioutil.ReadAll(stderr)
		if err != nil {
			fmt.Println("ReadAll stderr: ", err.Error())
			break
		}

		if len(bytesErr) != 0 {
			fmt.Println(fmt.Sprintf("stderr:%s", bytesErr))
			break
		}

		bytes, err := ioutil.ReadAll(stdout)
		if err != nil {
			fmt.Println("ReadAll stdout: ", err.Error())
			break
		}

		if err := cmd.Wait(); err != nil {
			fmt.Println("Wait: ", err.Error())
			break
		}
		fmt.Println(fmt.Sprintf("stdout: %s", bytes))
	}
	fmt.Println("exec success:", outfile)
	<-ch
}
func init() {
	videoSuffix = []string{"mp4", "mov", "mpeg"}
	configPath := "./config.ini"
	cfg, err := config.ReadDefault(configPath)
	if err != nil {
		fmt.Printf("config.ReadDefault error:%v\n", err)
		panic(fmt.Sprintf("config.ReadDefault error:%v", err))
		return
	}
	video_path, err = cfg.String("settings", "video_path")
	if err != nil {
		fmt.Println("err:", err)
	}
	exec_thread, _ = cfg.Int("settings", "exec_thread")
	if exec_thread == 0 {
		exec_thread = 1
	}
	video_after_path, _ = cfg.String("settings", "video_after_path")
	logoPath, _ = cfg.String("settings", "logo_folder")
	fmt.Println(fmt.Sprintf("video_path:%s, video_after_path:%s, logoPath:%s\n", video_path, video_after_path, logoPath))
}
func listFiles(dirPath string, meetSuffix []string) ([]string, error) {
	subFiles := make([]string, 0)
	dir, err := ioutil.ReadDir(dirPath)
	if err != nil {
		fmt.Println("listFiles:%v", err)
		return nil, err
	}
	for _, fi := range dir {
		if fi.IsDir() {
			continue
		}
		for i := 0; i < len(meetSuffix); i++ {
			if strings.HasSuffix(strings.ToLower(fi.Name()), meetSuffix[i]) {
				subFiles = append(subFiles, fi.Name())
			}
		}
	}
	return subFiles, nil
}
func fileExists(filePath string) bool {
	f, err := os.Open(filePath)
	if err != nil && os.IsNotExist(err) {
		return false
	}
	defer f.Close()
	return true
}
func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	go waitingRun()
	videos, _ := listFiles(video_path, videoSuffix)
	pathSep := string(os.PathSeparator)
	ch := make(chan int, exec_thread)
	logo := fmt.Sprintf("%s/logo_default.png", logoPath)
	for _, f := range videos {
		ch <- 1
		fmt.Println("-------- begin add watermarking video: --------", f)
		infile := video_path + pathSep + f
		outfile := video_after_path + pathSep + f
		cmd := exec.Command("ffprobe", "-v", "quiet", "-print_format", "json", "-show_streams", "-i", infile)

		modelInfo := execCmdInfo(cmd)
		if len(modelInfo.Streams) > 0 {
			for _, stream := range modelInfo.Streams {
				fmt.Println("width:", stream.Width, "height:", stream.Height)
				if stream.Width > 0 {
					logoNew := fmt.Sprintf("%s/logo_%d.png", logoPath, stream.Width)
					if fileExists(logoNew) {
						logo = logoNew
					}
					break
				}
			}
		}
		fmt.Println("current logo:", logo)
		cmd = exec.Command("ffmpeg", "-i", infile, "-acodec", "copy", "-vf", fmt.Sprintf("movie='%s'  [logo]; [in][logo] overlay=x=if(lt(mod(t\\,30)\\,2)\\,(W-w)/2\\,NAN ):y=(H-h) [out]", logo), "-y", outfile) //"-q:v", "2424723","-qscale", "6",
		go execCmd(cmd, outfile, ch)
	}
	for {
		if len(ch) == 0 {
			break
		}
		time.Sleep(3 * time.Second)
	}
	fmt.Println("-------- exec end! --------")
}
func waitingRun() {
	for {
		time.Sleep(3 * time.Second)
		fmt.Println("please waiting...")
	}
}
